package br.unisinos.aidk.searcher;

import br.unisinos.aidk.graph.Node;
import br.unisinos.aidk.graph.Problem;
import br.unisinos.aidk.graph.Queue;
import br.unisinos.aidk.graph.Solution;

public class Searcher<V> {

	private Queue<Node<V>> nodes = new Queue<Node<V>>();
	private SearchStrategy<V> str;
	//private HashSet<V> hash = new HashSet<V>();

	private Solution solution = new Solution();

	public Solution interactiveSearch(Problem<V> p, int value) {		
		for (int i = 0; i <= value; i++) {
			setStrategy(new DepthSearch<V>(i));
			Solution sol = search(p);
			if (sol != null)
				return sol;
		}
		return null;
	}

	public Solution search(Problem<V> p) {
		nodes.clean();
		Node<V> n = createNode(p);
		nodes.add(n);
		while (true) {
			if (nodes.isEmpty()) {
				return null;
			}
			Node<V> tmp = nodes.remove();
			if (p.isGoal(tmp.getValue())) {
				return generateSolution(tmp);
			} else {
				str.apply(nodes, p.expand(tmp));
			}
		}
	}

	private Solution generateSolution(Node<V> tmp) {
		solution = new Solution();		
		String t = tmp.getOperator(); 
		while(!t.equals(".")){
			solution.addStep(t);
			tmp = tmp.getParent();
			t = tmp.getOperator();
		}
		return solution;
	}

	private Node<V> createNode(Problem<V> p) {
		Node<V> root = new Node<V>();
		root.setValue(p.getInitialState());
		return root;
	}

	public SearchStrategy<V> getStrategy() {
		return str;
	}

	public void setStrategy(SearchStrategy<V> str) {
		this.str = str;
	}
}
